﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;

namespace Central.Linq.Mvc {
	/// <summary>
	/// Базовый контроллер для реализации
	/// автоматических фильтров
	/// </summary>
	/// <typeparam name="TViewModel"></typeparam>
#if !DEBUG

	[DebuggerStepThrough]
#endif
	public abstract class PreparableController<TViewModel> : Controller where TViewModel : IPreparable {
		private InfoManager _infoManager;
		private string _controllerName;
		private string _actionName;
		private string _userName;
		private readonly PreparableFiltersManager _filterManager;
		private const string preparable_username = "preparable_username";

		protected PreparableController(PreparableFiltersManager filterManager) {
			this._filterManager = filterManager;
		}

		/// <summary>
		/// Управлятор информацией по сущности
		/// </summary>
		/// <returns></returns>
		protected abstract InfoManager InitializeInfoManager();

		/// <summary>
		/// Переопределяет имя пользоватьеля при наличии авторизации на сайте
		/// </summary>
		/// <returns></returns>
		protected virtual string SetUserName() {
			return this._userName = Session[preparable_username].ToString();
		}

		protected override void Initialize(RequestContext requestContext) {
			base.Initialize(requestContext);
			if (String.IsNullOrEmpty(_userName)) {
				if (Session[preparable_username] == null) {
					this._userName = requestContext.HttpContext.Session.SessionID;
					Session[preparable_username] = this._userName;
				}
				else {
					this._userName = Session[preparable_username].ToString();
				}
			}
			this._userName = SetUserName();
			if (ViewData["queryable_controller"] != null && ViewData["queryable_action"] != null) {
				_controllerName = TempData["queryable_controller"].ToString();
				_actionName = TempData["queryable_action"].ToString();
			}
			else {
				_controllerName = this.ControllerContext.RouteData.Values["controller"].ToString();
				_actionName = this.ControllerContext.RouteData.Values["action"].ToString();
			}

			PreparableFilters quaryablefilters = _filterManager.Filters(_userName, _controllerName, _actionName);
			if (quaryablefilters != null) {
				this.Filters = quaryablefilters.ActionFilters;
			}
			else {
				this.Filters = new List<FilterDefinition>();
			}
		}

		public InfoManager ModelInfoManager {
			get {
				if (_infoManager == null) {
					this._infoManager = this.InitializeInfoManager();
				}
				return _infoManager;
			}
		}

		public IList<FilterDefinition> Filters { get; set; }

		[HttpPost]
		public ActionResult CreateFilter(FormCollection model, string queryable_action, string queryable_controller) {
			if (String.IsNullOrEmpty(queryable_action) || String.IsNullOrEmpty(queryable_controller)) return null;
			ViewBag.Fields = this.ModelInfoManager.FieldInformations;
			_controllerName = queryable_controller;
			_actionName = queryable_action;
			FilterParam filterParam = new FilterParam();
			filterParam.Name = model["ClientFilters.Name"].ToString();
			filterParam.DisplayName = model["ClientFilters.DisplayName"].ToString();
			filterParam.Operator = (FilterOperator)Enum.Parse(typeof(FilterOperator), model["ClientFilters.Operator"].ToString());
			filterParam.Value = !string.IsNullOrEmpty(model["ClientFilters.Value"].ToString()) ? model["ClientFilters.Value"].ToString() : null;
			FilterDefinition filter = InfoHelper.CreateFieldDefinition<TViewModel>(filterParam);
			this._filterManager.Add(_userName, _controllerName, _actionName, filter);
			return RedirectToAction(_actionName, _controllerName);
		}

		[HttpPost]
		public ActionResult DeleteFilter(string id, string queryable_action, string queryable_controller) {
			Guid _id = Guid.Parse(id);
			this._filterManager.DeleteFilter(_userName, queryable_controller, queryable_action, id);
			return RedirectToAction(queryable_action, queryable_controller);
		}

		public JsonResult ChangeOperators(string fieldName) {
			var selected = InfoHelper.ApplicableFilterOperators<TViewModel>(fieldName);
			var models = selected.Select(x => new { Name = x, DisplayName = OperatorsResource.ResourceManager.GetString(x).ToString() });
			return Json(models.ToArray(), JsonRequestBehavior.AllowGet);
		}
	}
}